<!---
	Copyright 2010 Edward Trudeau, Jeremy Battle
    This software is freely available under the MIT License: http://www.opensource.org/licenses/mit-license.php
    http://ayc.googlecode.com
    
--->

<!--- Custom tag that determines whether or not a given user has access to a given page function.  The access permissions are determined based on a structure called request.stSecurity, set in the application.cfm file based on values in the database and a persistent session structure of the same name.

Required attributes:
	Perm: text	- the description of the action to take
	Level: integer	- the level of permission required

Optional attributes:
	var: the caller variable to be set with the pass or fail value; defaults to caller.securityCheck

Action:
	The tag checks for required parameters; if any are missing, a syntax error is thrown to the caller.
	The tag checks for the permissions requested; if there is an error in the security structure, a general error is thrown to the caller.
	If the structure is correct but the value does not exist, the tag throws an access denied error but exits normally.
	If everything passes, the tag sets the caller variable and exits.
	
Caller variables:
	The tag returns caller.securityCheck = 1 if the check passes, and 0 otherwise
	
	History:
	7/15/05 EJT altered to allow user to wrap secure content in a tag set.
	
 --->
 
 <!--- execute the actual security test if this tag is called without an end tag or if this is the start of a start/end set. --->
 
 <cfif NOT thisTag.hasEndTag 
 		OR thisTag.executionMode EQ "start">
 
	 <cfparam name="attributes.var" default="securityCheck">
	 
	 <cfset "caller.#attributes.var#" = 0>
	 <cfset passed = "false">
	<cftry>
	
		<cfif NOT structKeyExists(session, "secexLogin") OR session.secexLogin NEQ "auth">
			<cfthrow type="denied" message="Access Denied" detail="You have requested an unpermitted or undefined action">
		</cfif>
		
		<cfif NOT isDefined("attributes.Perm") 
				OR NOT isDefined("attributes.level")
				OR NOT listFindNoCase(request.permLevels, attributes.level)>
			<cfthrow type="syntax" message="CF_securityCheck missing parameter" detail="The call to CF_securityCheck was missing a required parameter.  Please check the syntax for calling this tag.">
			<cfexit>
		</cfif>
		
		<cfif structKeyExists(request.stSecurity, "#attributes.Perm#")>
			<cfif listFindNoCase(request.permLevels, attributes.level) LTE listFindNoCase(request.permLevels, request.stSecurity["#attributes.Perm#"])>
				<cfset "caller.#attributes.var#" = 1>
				<cfset passed = "true">
			<cfelse>
				<cfthrow type="denied" message="Access Denied" detail="You have requested an unpermitted or undefined action">
			</cfif>
		<!--- couldn't find object type --->
		<cfelse>
			<cfthrow type="denied" message="Access Denied" detail="You have requested an unpermitted or undefined action">
		</cfif>
		
		<!--- if we got this far and the user PASSED, exitTemplate and execute the body in the tag; if the user failed, exitTag and resume after end tag. --->
		
		<cfif passed>
			<cfexit method="exittemplate">
		<cfelse>
			<cfexit method="exittag">
		</cfif>
		
		<cfcatch type="denied">
			<cfexit method="exittag">
		</cfcatch>
		
		<cfcatch type="Any">
			<cfrethrow>
		</cfcatch>
	</cftry>
	

</cfif>

